<?php

/**
 * 最终决定采用静态类，别在这里耗时间了
 *
 * @author heshun
 */
class Request {

    //static $info = array();
    static public $info   = array('domain' => NULL, 'mainDomain' => NULL, 'subDomain' => NULL, 'clientIp' => NULL, 'serverIp' => NULL,
        'uri' => NULL, 'url' => NULL, 'ua' => NULL, 'referer' => NULL, 'queryString' => NULL, 'isPost' => NULL);
    static private $_get;
    static private $_post;
    static private $_cookie;

    static private $instance = NULL;

    function __construct()
    {
        // 如果要取消$_GET等变量应在引导程序里面做，类里面尽量独立，不要实现一些运行时参数
        // 不推荐实例化，应采用Request::getInstance()方式
        return false;
    }

    static public function init()
    {
        self::$_get = $_GET;
        self::$_post = $_POST;
        self::$_cookie = $_COOKIE;
        // 去掉自动加的引号
        if (get_magic_quotes_gpc())
        {
            //self::$_get = array_walk_recursive(self::$_get, array($this, 'addslashes_deep'));
            //self::$_post = array_walk_recursive(self::$_post, array($this, 'addslashes_deep'));
            self::$_get = array_walk_recursive(self::$_get, create_function('&$value, $key', '$value = stripslashes($value);'));
            self::$_post = array_walk_recursive(self::$_post, create_function('&$value, $key', '$value = stripslashes($value);'));
        }
        self::$info = self::getRequestInfo();
    }

    static public function getDomain()
    {
        if (!isset(self::$info['domain']))
        {
            self::$info = array_merge(self::$info, self::parse_domain_2(parse_domain_1()));
        }

        return self::$info['domain'];
    }

    // 完整路径，带查询串
    static public function getRequestURI()
    {
        if (!isset(self::$info['uri']))
        {
            self::$info['uri'] = $_SERVER["REQUEST_URI"];
        }

        return self::$info['uri'];
    }

    // 不带查询串，前面不带/
    static public function getURL()
    {
        if (!isset(self::$info['url']))
        {
            self::$info['url'] = substr($_SERVER["SCRIPT_NAME"], 1);
        }

        return self::$info['url'];
    }
    
    static public function getQueryString()
    {
        if (!isset(self::$info['query_string']))
        {
            $request_info['uri'] = $_SERVER['REQUEST_URI'];
            if (strpos($request_info['uri'], '?') !== false)
            {
                $request_info['query_string'] = substr(strstr($request_info['uri'], '?'), 1);
                $request_info['url']          = @parse_url(substr($request_info['uri'], 0, strpos($request_info['uri'], '?')));
            }
            else
            {
                $request_info['query_string'] = '';
                $request_info['url']          = @parse_url($request_info['uri']);
            }

            $request_info['url'] = substr(@$request_info['url']['path'], 1);
            if ($request_info['url'] === '/' || $request_info['url'] == '')
            {
                $request_info['url'] = 'index.php';
            }

            // 将进行了目录级 rewrite 的数据放在 query_string 串里
            if (empty($request_info['query_string']) === true && strpos($request_info['url'], '/') > 0)
            {
                $request_info['query_string'] = basename($request_info['url']);
                if ($request_info['url'] === $request_info['query_string'])
                {
                    $request_info['query_string'] = '';
                }
            }
            self::$info = array_merge(self::$info, $request_info);
        }

        return self::$info['query_string'];
    }

    static public function getServerIp()
    {
        if (!isset(self::$info['serverIp']))
        {
            self::$info['serverIp'] = self::get_server_ip();
        }

        return self::$info['serverIp'];
    }

    static public function getClientIp()
    {
        if (!isset(self::$info['clientIp']))
        {
            self::$info['clientIp'] = self::get_client_ip();
        }

        return self::$info['clientIp'];
    }

    static public function getReferer()
    {
        if (!isset(self::$info['referer']))
        {
            self::$info['referer'] = $_SERVER['HTTP_REFERER'];
        }

        return self::$info['referer'];
    }

    static public function getUserAgent()
    {
        if (!isset(self::$info['ua']))
        {
            self::$info['ua'] = $_SERVER['HTTP_USER_AGENT'];
        }

        return self::$info['ua'];
    }

    static public function getRequestInfo()
    {
        static $request_info = NULL;

        if ($request_info === NULL)
        {
            $request_info = self::parse_domain_2(self::parse_domain_1());
            $request_info['client_ip'] = self::get_client_ip();
            $request_info['server_ip'] = self::get_server_ip();

            while (isset($_SERVER['REQUEST_URI']{1}) === true)
            {
                if ($_SERVER['REQUEST_URI']{0} === '/' && $_SERVER['REQUEST_URI']{1} === '/')
                {
                    $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 1);
                }
                else
                {
                    break;
                }
            }

            $request_info['uri'] = $_SERVER['REQUEST_URI'];
            if (strpos($request_info['uri'], '?') !== false)
            {
                $request_info['query_string'] = substr(strstr($request_info['uri'], '?'), 1);
                $request_info['url']          = @parse_url(substr($request_info['uri'], 0, strpos($request_info['uri'], '?')));
            }
            else
            {
                $request_info['query_string'] = '';
                $request_info['url']          = @parse_url($request_info['uri']);
            }

            $request_info['url'] = substr(@$request_info['url']['path'], 1);
            if ($request_info['url'] === '/' || $request_info['url'] == '')
            {
                $request_info['url'] = 'index.php';
            }

            // 将进行了目录级 rewrite 的数据放在 query_string 串里
            if (empty($request_info['query_string']) === true && strpos($request_info['url'], '/') > 0)
            {
                $request_info['query_string'] = basename($request_info['url']);
                if ($request_info['url'] === $request_info['query_string'])
                {
                    $request_info['query_string'] = '';
                }
            }

            /* 变量初始化 */
            if (isset($_SERVER['HTTP_USER_AGENT']) === true)
            {
                $request_info['ua'] = $_SERVER['HTTP_USER_AGENT'];
            }
            else
            {
                $request_info['ua'] = $_SERVER['HTTP_USER_AGENT'] = '';
            }

            if ($_SERVER['REQUEST_METHOD'] === 'POST')
            {
                $request_info['isPost'] = true;
            }
            else
            {
                $request_info['isPost'] = false;
            }
        }

        if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) === true)
        {
            $_SERVER['HTTP_ACCEPT_ENCODING'] = strtolower($_SERVER['HTTP_ACCEPT_ENCODING']);
        }
        else
        {
            $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
        }

        if (isset($_SERVER['HTTP_REFERER']) === true)
        {
            $request_info['referer'] = $_SERVER['HTTP_REFERER'];
        }
        else
        {
            $request_info['referer'] = $_SERVER['HTTP_REFERER'] = '';
        }

        if (isset($_SERVER['HTTP_ACCEPT']) === false)
        {
            $_SERVER['HTTP_ACCEPT'] = '';
        }

        return $request_info;
    }

    private function parse_domain_1()
    {
        if (isset($_SERVER['HTTP_X_FORWARDED_HOST']))
        {
            $domain = $_SERVER['HTTP_X_FORWARDED_HOST'];
        }
        elseif (isset($_SERVER['HTTP_HOST']))
        {
            $domain = $_SERVER['HTTP_HOST'];
        }
        elseif (isset($_SERVER['SERVER_NAME']))
        {
            $domain = $_SERVER['SERVER_NAME'];
        }
        else
        {
            $domain = false;
        }

        /* 去掉后面的端口信息 */
        if (strpos($domain, ':') !== false)
        {
            $domain = substr($domain, 0, strpos($domain, ':'));
        }

        return $domain;
    }

    //
    private function parse_domain_2($host)
    {
        $domain['domain'] = $host;

        $domain['main_domain'] = preg_replace("/.*?([^\.\/]+(\.(cn|com|net|org|gov|edu))+)$/", "\\1", $domain['domain']);
        if ($domain['main_domain'] !== $domain['domain'])
        {
            $domain['sub_domain'] = str_replace('.' . $domain['main_domain'], '', $domain['domain']);
        }
        else
        {
            /* 如果是无二级域名的访问，默认为 www 二级域名 */
            $domain['sub_domain'] = 'www';
            $domain['domain']     = 'www.' . $domain['domain'];
        }

        return $domain;
    }

    /* 获得用户的真实 IP 地址 */
    private function get_client_ip()
    {
        static $realip = NULL;

        if ($realip !== NULL)
        {
            return $realip;
        }

        if (isset($_SERVER))
        {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
            {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

                /* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
                foreach ($arr AS $ip)
                {
                    $ip = trim($ip);

                    if ($ip != 'unknown')
                    {
                        $realip = $ip;

                        break;
                    }
                }
            }
            elseif (isset($_SERVER['HTTP_CLIENT_IP']))
            {
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            }
            else
            {
                if (isset($_SERVER['REMOTE_ADDR']))
                {
                    $realip = $_SERVER['REMOTE_ADDR'];
                }
                else
                {
                    $realip = '0.0.0.0';
                }
            }
        }
        else
        {
            if (getenv('HTTP_X_FORWARDED_FOR'))
            {
                $realip = getenv('HTTP_X_FORWARDED_FOR');
            }
            elseif (getenv('HTTP_CLIENT_IP'))
            {
                $realip = getenv('HTTP_CLIENT_IP');
            }
            else
            {
                $realip = getenv('REMOTE_ADDR');
            }
        }

        preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
        $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';

        return $realip;
    }

    /* 获取服务器端的 IP 地址 */
    private function get_server_ip()
    {
        static $serverip = NULL;

        if ($serverip !== NULL)
        {
            return $serverip;
        }

        if (isset($_SERVER['SERVER_ADDR']))
        {
            $serverip = $_SERVER['SERVER_ADDR'];
        }
        else
        {
            $ip = @file_get_contents(DATA_PATH . '/SERVER_ADDR');
            if (empty($ip) === false)
            {
                preg_match('/\d{1,3}(?<!192|127)(?:\.\d{1,3}){3}/', $ip, $match);
                $serverip = trim($match[0]);
            }
        }

        if (empty($serverip) === true)
        {
            trigger_error('[LIB_DOMAIN] get_server_ip 函数获取地址出错，ip=' . $ip, E_USER_WARNING);

            $serverip = '0.0.0.0';
        }

        return $serverip;
    }
    
    static public function get_browser_type()
    {
        if (stripos($_SERVER['HTTP_ACCEPT'], 'wml') !== false || stripos($_SERVER['HTTP_ACCEPT'], 'wap') !== false || stripos($_SERVER['HTTP_ACCEPT'], 'wbmp') !== false || stripos($_SERVER['HTTP_USER_AGENT'], 'ucweb') !== false)
        {
            return 'WAP';
        }
        else
        {
            return 'WEB';
        }
    }
    
    
    
    
    
    
    
    
    
    
    private function callback_addslashes(&$value, $key)
    {
        $value = addslashes($value);
    }

    private function callback_stripslashes(&$value, $key)
    {
        $value = stripslashes($value);
    }

    // 参考fetch_get()
    static public function getGet($key, $type, $default = NULL)
    {
        if (isset(self::$_get[$key]) === false)
        {
            switch ($type)
            {
                case 'array':
                    return array();
                    break;
                case 'intval':
                    return ($default === NULL) ? 0   : (int)$default;
                    break;
                case 'floatval':
                    return ($default === NULL) ? 0.0 : (float)$default;
                    break;
                case 'bigval':
                    return ($default === NULL) ? 0   : bigval($default);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    // 无默认值的情况
                    if ($default === NULL)
                    {
                        return '';
                    }
                    // 仅有默认值的情况
                    elseif (strpos($default, '|') === false)
                    {
                        if ($type === 'string')
                        {
                            return (string)$default;
                        }
                        else
                        {
                            return trim((string)$default);
                        }
                    }
                    // 枚举的情况
                    else
                    {
                        $_value = explode('|', $default);

                        if ($type === 'string' || $type === 'binary')
                        {
                            return (string)$_value[0];
                        }
                        else
                        {
                            return trim((string)$_value[0]);
                        }
                    }
                    break;
            }
        }
        else
        {
            $value = self::$_get[$key];
            switch ($type)
            {
                case 'array':
                    $value = (array)$value;
                    return $value;
                    break;
                case 'intval':
                    return (int)$value;
                    break;
                case 'floatval':
                    return (float)$value;
                    break;
                case 'bigval':
                    return bigval($value);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    if ($type !== 'binary')
                    {
                        $value = replace_crlf((string)$value);
                    }
                    /* 枚举的情况 */
                    if ($default !== NULL)
                    {
                        if (strpos($default, '|') !== false)
                        {
                            $_value = explode('|', $default);
                            if ($value === '' || in_array($value, $_value) === false)
                            {
                                $value = (string)$_value[0];
                            }
                        }
                        elseif ($value === '')
                        {
                            $value = (string)$default;
                        }
                    }

                    if ($type === 'trim')
                    {
                        $value = trim($value);
                    }
                    return $value;
                    break;
            }
        }
    }

    // 复制代码为了保证效率，少一次函数调用开销
    static public function getPost($key)
    {
        if (isset(self::$_post[$key]) === false)
        {
            switch ($type)
            {
                case 'array':
                    return array();
                    break;
                case 'intval':
                    return ($default === NULL) ? 0   : (int)$default;
                    break;
                case 'floatval':
                    return ($default === NULL) ? 0.0 : (float)$default;
                    break;
                case 'bigval':
                    return ($default === NULL) ? 0   : bigval($default);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    // 无默认值的情况
                    if ($default === NULL)
                    {
                        return '';
                    }
                    // 仅有默认值的情况
                    elseif (strpos($default, '|') === false)
                    {
                        if ($type === 'string')
                        {
                            return (string)$default;
                        }
                        else
                        {
                            return trim((string)$default);
                        }
                    }
                    // 枚举的情况
                    else
                    {
                        $_value = explode('|', $default);

                        if ($type === 'string' || $type === 'binary')
                        {
                            return (string)$_value[0];
                        }
                        else
                        {
                            return trim((string)$_value[0]);
                        }
                    }
                    break;
            }
        }
        else
        {
            $value = self::$_post[$key];
            switch ($type)
            {
                case 'array':
                    $value = (array)$value;
                    return $value;
                    break;
                case 'intval':
                    return (int)$value;
                    break;
                case 'floatval':
                    return (float)$value;
                    break;
                case 'bigval':
                    return bigval($value);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    if ($type !== 'binary')
                    {
                        $value = replace_crlf((string)$value);
                    }
                    /* 枚举的情况 */
                    if ($default !== NULL)
                    {
                        if (strpos($default, '|') !== false)
                        {
                            $_value = explode('|', $default);
                            if ($value === '' || in_array($value, $_value) === false)
                            {
                                $value = (string)$_value[0];
                            }
                        }
                        elseif ($value === '')
                        {
                            $value = (string)$default;
                        }
                    }

                    if ($type === 'trim')
                    {
                        $value = trim($value);
                    }
                    return $value;
                    break;
            }
        }
    }

    static public function getCookie($key)
    {
        if (isset(self::$_cookie[$key]) === false)
        {
            switch ($type)
            {
                case 'array':
                    return array();
                    break;
                case 'intval':
                    return ($default === NULL) ? 0   : (int)$default;
                    break;
                case 'floatval':
                    return ($default === NULL) ? 0.0 : (float)$default;
                    break;
                case 'bigval':
                    return ($default === NULL) ? 0   : bigval($default);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    // 无默认值的情况
                    if ($default === NULL)
                    {
                        return '';
                    }
                    // 仅有默认值的情况
                    elseif (strpos($default, '|') === false)
                    {
                        if ($type === 'string')
                        {
                            return (string)$default;
                        }
                        else
                        {
                            return trim((string)$default);
                        }
                    }
                    // 枚举的情况
                    else
                    {
                        $_value = explode('|', $default);

                        if ($type === 'string' || $type === 'binary')
                        {
                            return (string)$_value[0];
                        }
                        else
                        {
                            return trim((string)$_value[0]);
                        }
                    }
                    break;
            }
        }
        else
        {
            $value = self::$_cookie[$key];
            switch ($type)
            {
                case 'array':
                    $value = (array)$value;
                    return $value;
                    break;
                case 'intval':
                    return (int)$value;
                    break;
                case 'floatval':
                    return (float)$value;
                    break;
                case 'bigval':
                    return bigval($value);
                    break;
                case 'string':
                case 'binary':
                case 'trim':
                    if ($type !== 'binary')
                    {
                        $value = replace_crlf((string)$value);
                    }
                    /* 枚举的情况 */
                    if ($default !== NULL)
                    {
                        if (strpos($default, '|') !== false)
                        {
                            $_value = explode('|', $default);
                            if ($value === '' || in_array($value, $_value) === false)
                            {
                                $value = (string)$_value[0];
                            }
                        }
                        elseif ($value === '')
                        {
                            $value = (string)$default;
                        }
                    }

                    if ($type === 'trim')
                    {
                        $value = trim($value);
                    }
                    return $value;
                    break;
            }
        }
    }

    static public function setCookie($key, $value, $domain = '', $expire_time = 2592000, $httponly = true)
    {
        if (empty($value))
        {
            $expire_time = -1;
        }
        else
        {
            $expire_time = REQUEST_TIME + $expire_time;
        }

        if ($domain === '')
        {
            $domain = '.' . MAIN_DOMAIN;
        }

        $cookie_path = '/';

        $secure = (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) ? true : false;
    /* 另一种写法
        $secure = (isset($_SERVER['SERVER_PORT']) && ($_SERVER['SERVER_PORT'] == '443')) ? true : false;
    */

        if (BROWSER_TYPE === 'wap')
        {
            return setcookie($key, $value, $expire_time, $cookie_path, $domain, $secure, false);
        }
        else
        {
            return setcookie($key, $value, $expire_time, $cookie_path, $domain, $secure, $httponly);
        }
    }


    /*
    public function __get($key)
    {
        if (!array_key_exists($key, $this->_requestInfo))
        {
            return NULL;
        }

        if ($this->_requestInfo[$key] === NULL)
        {
            switch ($key)
            {
                case 'clientIp';
                    $this->_requestInfo[$key] = self::get_client_ip();
                    break;
                case 'url':
                    $this->_requestInfo[$key] = substr($_SERVER["SCRIPT_NAME"], 1);
                    break;
                case 'domain':
                case 'mainDomain':
                case 'subDomain':
                    // 对于关联数组，array_merge后者将覆盖前面的相同键值
                    $this->_requestInfo = array_merge($this->_requestInfo, self::parse_domain_2(self::parse_domain_1()));
                    break;
                case 'isPost':
                    $this->_requestInfo[$key] = $_SERVER['REQUEST_METHOD'] == 'POST';
                    break;
            }
        }

        return $this->_requestInfo[$key];
    }

    public function __set($key, $value)
    {
        // 只便用内置变量，这里也可以放开限制
        if (!isset($this->_requestInfo[$key]))
        {
            return NULL;
        }

        $this->_requestInfo[$key] = $value;
    }

    static public function getInstance()
    {
        if (self::$instance === NULL)
        {
            self::$instance = new self;
        }
        return self::$instance;
    }
    */
}
?>
